package com.fy.fyspace.controller;

import cn.hutool.core.util.StrUtil;
import com.fy.fyspace.common.annotation.GlobalInterceptor;
import com.fy.fyspace.common.result.Result;
import com.fy.fyspace.common.utils.AiUtils;
import com.fy.fyspace.constant.KeysConstant;
import com.fy.fyspace.constant.ResultMessageConstant;
import com.fy.fyspace.ex.handler.ExceptionHandler;
import com.fy.fyspace.model.dto.outpainting.CreatePictureOutPaintingTaskDTO;
import com.fy.fyspace.model.vo.outpainting.CreateOutPaintingTaskVO;
import com.fy.fyspace.model.vo.outpainting.GetOutPaintingTaskVO;
import com.fy.fyspace.model.vo.user.UserSessionVO;
import com.fy.fyspace.service.AIService;
import com.fy.fyspace.service.ChatConstantService;
import com.zhipu.oapi.service.v4.model.ModelData;
import io.reactivex.Flowable;
import io.reactivex.schedulers.Schedulers;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.junit.platform.commons.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;

/**
 * AI功能控制器
 * 提供AI图片处理相关接口
 */
@Api(tags = "AI接口", description = "提供AI图片处理相关功能")
@RestController
@RequestMapping("/ai")
@Slf4j
public class AIController {

    @Resource
    private AIService aiService;

    @Autowired
    private ChatConstantService chatConstantService;

    /**
     * 获取随机问题列表
     * 从预设问答库中随机获取5个常见问题，用于展示和引导用户
     *
     * @return Result<List < String>> 随机问题列表
     */
    @ApiOperation(value = "获取随机问题列表", notes = "从预设问答库中随机获取5个常见问题，优先从缓存获取")
    @ApiResponses({
            @ApiResponse(code = 200, message = "获取成功"),
            @ApiResponse(code = 400, message = "请求错误"),
    })
    @GetMapping("/questions")
    @GlobalInterceptor(checkLogin = false)
    public Result<List<String>> getQuestions() {
        log.info("开始获取随机问题列表");
        return chatConstantService.getQuestions();
    }

    /**
     * 获取预设问答内容
     * 根据问题获取预设的回答内容，并更新访问计数
     *
     * @param question 预设问题内容
     * @return 预设的回答内容
     */
    @ApiOperation(value = "获取预设问答", notes = "根据问题获取系统预设的标准回答，并记录访问次数")
    @ApiResponses({
            @ApiResponse(code = 200, message = "获取成功"),
            @ApiResponse(code = 400, message = "请求错误"),
    })
    @GetMapping("/ChatConstant/{question}")
    public Result<String> chatConstant(
            @ApiParam(name = "question", value = "预设问题内容", required = true, example = "如何上传图片？")
            @PathVariable("question") String question
    ) {
        log.info("开始处理预设问答请求, 问题: {}", question);

        // 参数校验
        ExceptionHandler.throwIf(StrUtil.isBlank(question),
                ResultMessageConstant.PARAMS_ERROR);
        return chatConstantService.getAnswer(question);
    }


    /**
     * 创建 AI 扩图任务
     *
     * @param createPictureOutPaintingTaskRequest 创建扩图任务请求参数
     * @param httpSession                         会话信息
     * @return 创建的扩图任务信息
     */
    @ApiOperation(value = "创建AI扩图任务", notes = "根据指定图片创建AI扩图任务，支持自定义扩展参数")
    @ApiResponses({
            @ApiResponse(code = 200, message = "获取成功"),
            @ApiResponse(code = 400, message = "服务器内部错误")
    })
    @PostMapping("/outPainting/createTask")
    public Result<CreateOutPaintingTaskVO> createPictureOutPaintingTask(
            @RequestBody CreatePictureOutPaintingTaskDTO createPictureOutPaintingTaskRequest,
            HttpSession httpSession) {
        log.info("开始处理图片内容扩展请求, 参数: {}", createPictureOutPaintingTaskRequest);

        ExceptionHandler.throwIf(createPictureOutPaintingTaskRequest == null ||
                        createPictureOutPaintingTaskRequest.getPictureId() == null,
                ResultMessageConstant.PARAMS_ERROR);

        UserSessionVO loginUser = (UserSessionVO) httpSession.getAttribute(KeysConstant.LOGIN_SESSION_KEY);
        CreateOutPaintingTaskVO response = aiService.createPictureOutPaintingTask(createPictureOutPaintingTaskRequest,
                loginUser);

        log.info("图片内容扩展任务创建成功: {}", response.getCode());
        return Result.success(response);
    }

    /**
     * 获取 AI 扩图任务进度
     *
     * @param taskId 任务ID
     * @return 任务进度信息
     */
    @ApiOperation(value = "获取AI扩图任务进度", notes = "根据任务ID查询AI扩图任务的处理进度")
    @ApiResponses({
            @ApiResponse(code = 200, message = "获取成功"),
            @ApiResponse(code = 400, message = "服务器内部错误")
    })
    @GetMapping("/outPainting/getTask")
    public Result<GetOutPaintingTaskVO> getPictureOutPaintingTask(@RequestParam String taskId) {
        log.info("查询图片内容扩展任务状态, 任务ID: {}", taskId);
        ExceptionHandler.throwIf(StrUtil.isBlank(taskId), ResultMessageConstant.PARAMS_ERROR);
        GetOutPaintingTaskVO task = aiService.getOutpaintingTaskStatus(taskId);

        return Result.success(task);
    }

    /**
     * 获取AI任务列表
     */
    @ApiOperation(value = "获取AI任务列表", notes = "获取不同进度的AI任务")
    @ApiResponses({
            @ApiResponse(code = 200, message = "获取成功"),
            @ApiResponse(code = 400, message = "获取失败")
    })
    @GetMapping("/getAiTasks")
    @GlobalInterceptor
    public Result getAITasks(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer pageSize,
            @RequestParam(required = false) String prompt,
            @RequestParam(required = false) String taskStatus) {
        return aiService.getAITasks(page, pageSize, prompt, taskStatus);
    }

    /**
     * 获取AI生成的图片列表
     */
    @ApiOperation(value = "获取AI生成的图片列表", notes = "从aipicture表中获取AI生成的图片")
    @ApiResponses({
            @ApiResponse(code = 200, message = "获取成功"),
            @ApiResponse(code = 400, message = "获取失败")
    })
    @GetMapping("/getAIPictures")
    @GlobalInterceptor
    public Result getAIPictures(
            @RequestParam(required = false) Integer page,
            @RequestParam(required = false) Integer pageSize,
            @RequestParam(required = false) String prompt) {
        return aiService.getAIPictures(page, pageSize, prompt);
    }

    /**
     * 删除AI图片
     */
    @ApiOperation(value = "删除AI图片", notes = "根据任务ID删除AI生成的图片")
    @ApiResponses({
            @ApiResponse(code = 200, message = "删除成功"),
            @ApiResponse(code = 400, message = "删除失败")
    })
    @PostMapping("/del")
    @GlobalInterceptor
    public Result deleteAIPictures(@RequestParam(required = true) String picIds) {
        log.info("开始删除AI图片, picIds: {}", picIds);
        return aiService.deleteAIPictures(picIds);
    }


    @GetMapping("/chat/{prompt}")
    public SseEmitter generateQuestionSSE(@PathVariable String prompt) {
        // 建立 SSE 连接对象，0 表示不超时
        SseEmitter emitter = new SseEmitter(0L);

        String msg = "你是蜂云盒子平台的智能客服，请直接回答用户问题。如果问题与平台无关，请礼貌说明你只能回答与平台相关的问题。不要解释你的分析过程，直接给出答案。以下是平台功能文档：\n" +
                "蜂云盒子是一个功能强大的综合性文件管理和AI创作平台。该平台提供个人网盘服务，支持文件的上传、下载、分享和管理，同时具备专业的图片处理和AI功能。" +
                "【文件管理功能】" +
                "系统支持多种上传方式：普通上传、批量上传和分片上传（适用于大文件），单个文件大小限制为5MB（非管理员用户）。支持的文件格式包括：图片(JPG/JPEG/PNG/GIF/WebP)、视频(MP4/AVI/MOV)、音频(MP3/WAV)、文档(PDF/DOC/DOCX/XLS/XLSX/TXT)等。提供完整的文件管理功能：文件分类、重命名、移动、复制、删除、搜索和批量操作。系统采用回收站机制，删除的文件会先进入回收站，可以在30天内恢复，超期则自动清除。支持文件在线预览功能，可直接查看图片、文档等内容。" +
                "【图片管理功能】" +
                "系统支持所有主流图片格式，提供专业的图片管理功能：1)标签管理：每张图片最多可添加4个标签，支持自定义标签分类；2)智能审核：上传的图片自动进行内容审核，确保合规；3)多维检索：支持按分类、标签、上传时间、文件大小等条件组合检索；4)缩略图功能：自动生成WebP格式的缩略图，支持多种尺寸预览；5)图片编辑：支持裁剪、旋转、调整大小等基础编辑功能；6)批量处理：支持批量添加标签、修改分类、导出等操作。" +
                "【AI功能模块】" +
                "1. 智能对话：采用流式响应机制，提供实时的问答服务。可回答系统使用问题，提供智能建议，支持上下文理解。" +
                "2. 图片扩展：支持对已有图片进行智能扩展，特性包括：" +
                "   - 支持上下左右四个方向扩展，默认各100像素" +
                "   - 提供最佳质量模式和限制图片尺寸模式" +
                "   - 原始图片要求：分辨率不低于512x512像素，文件大小不超过5MB" +
                "   - 实时任务进度查看，支持批量处理" +
                "   - 智能内容匹配，保持画面自然过渡" +
                "【空间管理功能】" +
                "为每个用户提供独立的存储空间，具体特性：1)空间配额：基础用户5GB，高级用户20GB，企业用户不限；2)空间监控：实时显示存储用量、文件分布；3)分享功能：支持文件/文件夹分享，可设置访问密码和有效期；4)版本控制：重要文件支持历史版本管理；5)安全存储：使用阿里云OSS作为存储后端，所有文件经过加密存储。" +
                "【系统安全保障】" +
                "1)登录保护：支持两步验证，异地登录提醒；2)传输加密：全程HTTPS加密传输；3)病毒扫描：文件上传自动查杀病毒；4)操作审计：记录所有关键操作日志；5)自动备份：系统每日自动备份用户数据。" +
                "【使用建议和注意事项】" +
                "1. 上传失败常见原因：文件大小超限、格式不支持、空间不足，请先进行相应检查。" +
                "2. 图片审核未通过会提供具体原因说明，可根据提示修改后重新上传。" +
                "3. 建议定期整理文件，及时备份重要数据。" +
                "4. 如需扩容或开通高级功能，可联系客服升级账户。" +
                "【问题解决与支持】" +
                "1. 常见问题可通过AI助手获取即时帮助。" +
                "2. 技术支持时间：周一至周日 9:00-22:00。" +
                "3. 如遇到无法解决的问题，请联系管理员QQ：2285114622。" +
                "4. 重要通知和系统更新会通过站内信发送，请及时查看。\n\n" +
                "用户问题：" + prompt + "\n" +
                "请直接回答问题，不要输出分析过程。如果是无关问题，请礼貌说明你只能回答平台相关问题。";
        // AI 生成的流式响应结果
        Flowable<ModelData> modelDataFlowable = AiUtils.aiCallerFlow(msg);

        modelDataFlowable
                // 指定观察者的线程池
                .observeOn(Schedulers.io())
                // 从智谱的响应中获取数据
                .map(chunk -> chunk.getChoices().get(0).getDelta().getContent())
                // 去掉响应中多余的空格和双引号
                .map(message -> message.replaceAll("\\s", "").replace("\"", ""))
                // 去掉为空字符串的响应
                .filter(StringUtils::isNotBlank)
                .flatMap(message -> {
                    // 将字符串转换为字符数组以便后续业务处理
                    List<Character> charList = new ArrayList<>();
                    for (char c : message.toCharArray()) {
                        charList.add(c);
                    }
                    return Flowable.fromIterable(charList);
                })
                .doOnNext(c -> {
                    try {
                        // 发送字符，确保没有双引号
                        emitter.send(SseEmitter.event()
                                .data(String.valueOf(c))
                                .name("message"));
                    } catch (Exception e) {
                        log.error("发送消息失败: {}", e.getMessage());
                    }
                })
                .doOnComplete(() -> {
                    try {
                        emitter.send(SseEmitter.event().name("complete"));
                        emitter.complete();
                    } catch (Exception e) {
                        log.error("发送完成消息失败: {}", e.getMessage());
                    }
                })
                .subscribe();
        return emitter;
    }

}